﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using HelixToolkit.Wpf;
using System.Windows.Media.Media3D;
using System.Text.RegularExpressions;
using System.Globalization;
using System.IO;


namespace PDBSmart
{
    public struct MyPoints
    {
        public ModelUIElement3D Element;
        public Atom Atom;
        public MyPoints(Atom Atom, ModelUIElement3D Model)
        {
            this.Atom = Atom;
            this.Element = Model;
        }
    }

    public struct Amino
    {
        public int Number;
        public AminoType AminoType;
        public List<Atom> Atoms;
    }

    public class Atom
    {
        public int Number;
        public Point3D Point;
        public AtomType AtomType;
        public ModelUIElement3D ModelUiElement3D;
        public Atom(int Number, Point3D Point, AtomType AtomType)
        {
            this.AtomType = AtomType;
            this.Number = Number;
            this.Point = Point;
        }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public Material SelectedMaterial = Materials.Hue;
        public List<MyPoints> GeometryList { get; set; }
        public Dictionary<int, List<Amino>> Models { get; set; }
        public Dictionary<int, List<object>> UIChildren { get; set; }
        public ModelUIElement3D CurrentElemtent { get; set; }
        public List<int> CurrentModelNumber { get; set; }

        public List<Atom> SelectedAtoms { get; set; }
        public List<ModelUIElement3D> SelectedModelUIs { get; set; }

        public List<Amino> Aminos { get; set; }
        public string Source;
        public MainWindow()
        {
            InitializeComponent();
            Models = new Dictionary<int, List<Amino>>();
            GeometryList = new List<MyPoints>();
            CurrentElemtent = new ModelUIElement3D();
            Aminos = new List<Amino>();
            SelectedAtoms = new List<Atom>();
            CurrentModelNumber = new List<int>();
            UIChildren = new Dictionary<int, List<object>>();
            SelectedModelUIs = new List<ModelUIElement3D>();
        }

        private void ContainerElementMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                var element = sender as ModelUIElement3D;
                var model = element.Model as GeometryModel3D;
                var t = model.Geometry as MeshGeometry3D;
                var points = t.Positions;
                //if (model.Material == Materials.Green)
                //    model.Material = Materials.White;
                model.Material = Materials.White;
                e.Handled = true;
            }
        }

        private void ZoomExtents_Click(object sender, RoutedEventArgs e)
        {
            view1.ZoomExtents(500);
        }

        private Point startPoint;
        private Rectangle rect;

        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            bool shift = (Keyboard.IsKeyDown(Key.LeftShift));
            var p = e.GetPosition(view1);

            Vector3D n;
            var ray = Viewport3DHelper.Point2DtoRay3D(view1.Viewport, p);
            var hits = Viewport3DHelper.FindHits(view1.Viewport, p);

            var helix = (HelixViewport3D)sender;
            Point position = e.GetPosition(helix);
            Visual3D obj = helix.FindNearestVisual(new Point(ray.Origin.X, ray.Origin.Y));
            Point3D? findNearestPoint = helix.FindNearestPoint(position);

            //canvas.Children.Remove(rect);
            startPoint = e.GetPosition(view1);

            rect = new Rectangle
            {
                Stroke = Brushes.LightBlue,
                StrokeThickness = 2
            };
            Canvas.SetLeft(rect, startPoint.X);
            Canvas.SetTop(rect, startPoint.X);
            //canvas.Children.Add(rect);
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Released || rect == null)
                return;

            //var pos = e.GetPosition(canvas);

            //var x = Math.Min(pos.X, startPoint.X);
            //var y = Math.Min(pos.Y, startPoint.Y);

            //var w = Math.Max(pos.X, startPoint.X) - x;
            //var h = Math.Max(pos.Y, startPoint.Y) - y;

            //rect.Width = w;
            //rect.Height = h;

            //Canvas.SetLeft(rect, x);
            //Canvas.SetTop(rect, y);
        }

        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            //canvas.Children.Remove(rect);

        }

        private void Calculate_Click(object sender, RoutedEventArgs e)
        {
            foreach (var modelNumber in CurrentModelNumber)
            {

                var list = (
                            from amino in Models[modelNumber]
                            from atom in amino.Atoms
                            where ((GeometryModel3D) atom.ModelUiElement3D.Model).Material.Equals(SelectedMaterial)
                            select atom
                           ).ToList();

                if (list.Count < 4)
                    return;

                DihedralAnglesTextBox.Text = default(string);
                for (int i = 0; i < list.Count - 3; i++)
                {
                    var tors = Tors(list[i].Point, list[i + 1].Point, list[i + 2].Point, list[i + 3].Point);

                    DihedralAnglesTextBox.Text += string.Format("{0:#.###}\n", tors);
                }
            }
        }

        private double Tors(Point3D i, Point3D j, Point3D k, Point3D l)
        {
            double xij = i.X - j.X;
            double yij = i.Y - j.Y;
            double zij = i.Z - j.Z;
            double xkj = k.X - j.X;
            double ykj = k.Y - j.Y;
            double zkj = k.Z - j.Z;
            double xkl = k.X - l.X;
            double ykl = k.Y - l.Y;
            double zkl = k.Z - l.Z;
            double dxi = (yij * zkj) - (zij * ykj);
            double dyi = (zij * xkj) - (xij * zkj);
            double dzi = (xij * ykj) - (yij * xkj);
            double gxi = (zkj * ykl) - (ykj * zkl);
            double gyi = (xkj * zkl) - (zkj * xkl);
            double gzi = (ykj * xkl) - (xkj * ykl);

            double ct = dxi * gxi + dyi * gyi + dzi * gzi;

            double bi = Math.Sqrt(dxi * dxi + dyi * dyi + dzi * dzi);
            double bk = Math.Sqrt(gxi * gxi + gyi * gyi + gzi * gzi);

            double z1 = 1 / bi;
            double z2 = 1 / bk;
            ct = ct * z1 * z2;
            double ap = Math.Acos(ct);
            double s = xkj * (dzi * gyi - dyi * gzi) + ykj * (dxi * gzi - dzi * gxi) + zkj * (dyi * gxi - dxi * gyi);

            if (s < 0) ap = -1.0 * ap;
            ap = ap > 0 ? Math.PI - ap : -(Math.PI + ap);
            return ap * 180 / Math.PI;

        }

        private void OpenFile_Click(object sender, RoutedEventArgs e)
        {
            Stream myStream = null;

            Microsoft.Win32.OpenFileDialog openFileDialog1 = new Microsoft.Win32.OpenFileDialog();

            openFileDialog1.InitialDirectory = @"C:\Users\Пользователь\Documents\Visual Studio 2012\Projects\PDBSmart";
            openFileDialog1.Filter = "pdb files (*.pdb)|*.pdb";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == true)
            {
                if ((myStream = openFileDialog1.OpenFile()) != null)
                {
                    using (var str = new StreamReader(myStream))
                    {
                        string line;
                        int modelNumber = 1;
                        int atomNumber = 1;
                        int atomInAminoNumber = 1;

                        int aminoNumber = -1;
                        Models.Add(modelNumber, new List<Amino>());

                        while ((line = str.ReadLine()) != null)
                        {
                            if (line.StartsWith("MODEL"))
                            {
                                if(modelNumber != 1)Models.Add(modelNumber, new List<Amino>());
                                atomNumber = 1;
                                aminoNumber = -1;
                                continue;
                            }
                            if (line.StartsWith("ENDMDL"))
                            {
                                modelNumber++;
                                continue;
                            }

                            if (line.StartsWith("ATOM"))
                            {
                                AtomType atomType;
                                if (Enum.TryParse(line.Substring(13, 4), out atomType))
                                {

                                    AminoType aminoType;
                                    var g = line.Substring(17, 3);
                                    if (Enum.TryParse(g, out aminoType))
                                    {

                                        double x, y, z;
                                        var culture = new NumberFormatInfo() { NumberDecimalSeparator = ".", NegativeSign = "-" };
                                        Point3D point = new Point3D(Convert.ToDouble(line.Substring(31, 8).Replace(" ", default(string)), culture),
                                                Convert.ToDouble(line.Substring(39, 8).Replace(" ", default(string)), culture),
                                                Convert.ToDouble(line.Substring(47, 8).Replace(" ", default(string)), culture));
                                        if (atomType == AtomType.N)
                                        {
                                            
                                            Models[modelNumber].Add(new Amino()
                                            {
                                                AminoType = aminoType,
                                                Atoms = new List<Atom>()
                                                        {
                                                            new Atom(atomInAminoNumber, point, atomType)
                                                        },
                                                        Number = ++aminoNumber
                                            });
                                        }
                                        else
                                        {
                                            Models[modelNumber][aminoNumber].Atoms.Add(new Atom(atomInAminoNumber, point, atomType));
                                        }
                                    }
                                }
                                atomNumber++;
                            }
                        }
                    }
                }
                modelList.ItemsSource = Models.Keys;
                //CurrentModelNumber = 1;
            }
        }

        private List<LinesVisual3D> DrawConnections(List<Amino> list)
        {
            var result = new List<LinesVisual3D>();

            for (int i = 0; i < list.Count - 1; i++)
            {
                var cpoint = list[i].Atoms.First(s => s.AtomType == AtomType.C);
                var npoint = list[i + 1].Atoms.First(s => s.AtomType == AtomType.N);

                var lines = new LinesVisual3D { Color = Colors.Gold };
                
                lines.Points.Add(cpoint.Point);
                lines.Points.Add(npoint.Point);
                result.Add(lines);
                //view1.Children.Add(lines);

            }

            return result;
        }

        private List<object> DrawAmino(Amino amino)
        {
            var result = new List<object>();
            var me = new MeshBuilder();
            GeometryModel3D geometry = new GeometryModel3D();
            var element = new ModelUIElement3D();
            var lines = new LinesVisual3D { Color = Colors.White };
            Atom N, ND1, ND2, NE, NE1, NE2, NZ, NH1, NH2, C, CA, CB, CG, CG1, CG2, CD, CD1, CD2, CE, CE1, CE2, CE3, CZ, CZ2, O, OG, OG1, OD1, OD2, OE1, OE2, OH, OXT, SD, SG;
            foreach (var atom in amino.Atoms)
            {
                me = new MeshBuilder();
                geometry = new GeometryModel3D();
                element = new ModelUIElement3D();

                me.AddSphere(atom.Point, 0.08);
                geometry.Geometry = me.ToMesh();
                geometry.Material = Utils.GetColorByAtomType(atom.AtomType);
                element.Model = geometry;



                element.MouseDown += ElementOnMouseDown;
                atom.ModelUiElement3D = element;
                result.Add(element);
            }
            N = amino.Atoms.First(s => s.AtomType == AtomType.N);
            CA = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CA);
            C = amino.Atoms.First(s => s.AtomType == AtomType.C);
            O = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.O);
            if (O == null)
            {
                lines = new LinesVisual3D { Color = Colors.White };
                lines.Points.Add(N.Point);
                lines.Points.Add(CA.Point);
                result.Add(lines);
                lines = new LinesVisual3D { Color = Colors.White };
                lines.Points.Add(CA.Point);
                lines.Points.Add(C.Point);
                result.Add(lines);
                return result;
            }
            if (CA == null)
            {
                lines = new LinesVisual3D { Color = Colors.White };
                lines.Points.Add(N.Point);
                lines.Points.Add(C.Point);
                result.Add(lines);
                lines = new LinesVisual3D { Color = Colors.White };
                lines.Points.Add(C.Point);
                lines.Points.Add(O.Point);
                result.Add(lines);
                return result;
            }

            lines = new LinesVisual3D { Color = Colors.White };
            lines.Points.Add(N.Point);
            lines.Points.Add(CA.Point);
            result.Add(lines);
            lines = new LinesVisual3D { Color = Colors.White };
            lines.Points.Add(CA.Point);
            lines.Points.Add(C.Point);
            result.Add(lines);
            lines = new LinesVisual3D { Color = Colors.White };
            lines.Points.Add(C.Point);
            lines.Points.Add(O.Point);
            result.Add(lines);

            switch (amino.AminoType)
            {
                case AminoType.MET:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    SD = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.SD);
                    CE = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE);

                    if (CB == null || CG == null || SD == null || CE == null)
                        return result;
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(SD.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(SD.Point);
                    lines.Points.Add(CE.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.ASN:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    OD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OD1);
                    ND2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.ND2);
                    if (CB == null || CG == null || OD1 == null || ND2 == null)
                        return result;
                    
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(OD1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(ND2.Point);
                    result.Add(lines);

                    #endregion
                    break;

                case AminoType.VAL:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG1);
                    CG2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG2);
                    if (CB == null || CG1 == null || CG2 == null)
                        return result;
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    //me.AddCylinder(CB.Point, CG1.Point);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG1.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG2.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.THR:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    OG1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OG1);
                    CG2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG2);
                    if (CB == null || OG1 == null || CG2 == null)
                        return result;
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(OG1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG2.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.CYS:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    SG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.SG);
                    if (CB == null || SG == null)
                        return result;


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(SG.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.ARG:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD);

                    NE = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NE);
                    CZ = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CZ);
                    NH1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NH1);
                    NH2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NH2);

                    if (CB == null || CG == null || CD == null || NE == null
                        || CZ == null || NH1 == null || NH2 == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CD.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(NE.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(NE.Point);
                    lines.Points.Add(CZ.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(NH2.Point);
                    lines.Points.Add(CZ.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(NH1.Point);
                    lines.Points.Add(CZ.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.PRO:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD);

                    if (CB == null || CG == null || CD == null)
                        return result;


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CD.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(N.Point);
                    result.Add(lines);


                    #endregion
                    break;
                case AminoType.LYS:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD);
                    CE = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE);
                    NZ = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NZ);
                    if (CB == null || CG == null || CD == null || CE == null || NZ == null)
                        return result;


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CD.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(CE.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(NZ.Point);
                    lines.Points.Add(CE.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.SER:
                    #region

                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    OG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OG);
                    if (CB == null || OG == null)
                        return result;


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(OG.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.LEU:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD1);
                    CD2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD2);
                    if (CB == null || CG == null || CD1 == null || CD2 == null)
                        return result;



                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(CD1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(CD2.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.ILE:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG1);
                    CG2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG2);
                    CD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD1);
                    if (CB == null || CG1 == null || CG2 == null || CD1 == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG1.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG2.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG1.Point);
                    lines.Points.Add(CD1.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.HIS:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    ND1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.ND1);
                    CD2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD2);
                    CE1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE1);
                    NE2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NE2);
                    if (CB == null || CG == null || ND1 == null || CD2 == null
                        || CE1 == null || NE2 == null)
                        return result;


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(ND1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CE1.Point);
                    lines.Points.Add(ND1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CE1.Point);
                    lines.Points.Add(NE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(NE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.GLY:
                    #region


                    OXT = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OXT);
                    if (OXT == null)
                        break;
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(C.Point);
                    lines.Points.Add(OXT.Point);
                    result.Add(lines);

                    #endregion
                    break;

                case AminoType.ALA:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);

                    if (CB == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.PHE:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD1);
                    CD2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD2);
                    CE1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE1);
                    CE2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE2);
                    CZ = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CZ);
                    if (CB == null || CG == null || CD1 == null || CD2 == null ||
                        CE1 == null || CE2 == null || CZ == null)
                        return result;


                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(CD1.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD1.Point);
                    lines.Points.Add(CE1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ.Point);
                    lines.Points.Add(CE1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.TYR:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD1);
                    CD2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD2);
                    CE1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE1);
                    CE2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE2);
                    CZ = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CZ);
                    OH = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OH);
                    if (CB == null || CG == null || CD1 == null || CD2 == null
                        || CE1 == null || CE2 == null || CZ == null || OH == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(CD1.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD1.Point);
                    lines.Points.Add(CE1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ.Point);
                    lines.Points.Add(CE1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ.Point);
                    lines.Points.Add(OH.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.GLN:
                    #region
                   // www.fli-leibniz.de 
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD);
                    NE2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NE2);
                    OE1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OE1);
                    OXT = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OXT);
                    if (CB == null || CG == null || CD == null || NE2 == null
                        || OE1 == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CD.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(OE1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(NE2.Point);
                    result.Add(lines);
                    if (OXT == null)
                        break;
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(C.Point);
                    lines.Points.Add(OXT.Point);
                    result.Add(lines);
                    #endregion
                    break;

                case AminoType.GLU:
                    #region

                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD);

                    OE1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OE1);
                    OE2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OE2);

                    if (CB == null || CG == null || CD == null || OE1 == null || OE2 == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CD.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(OE1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD.Point);
                    lines.Points.Add(OE2.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.ASP:
                    #region

                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);

                    OD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OD1);
                    OD2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.OD2);
                    if (CB == null || CG == null || OD1 == null || OD2 == null)
                        return result;

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(OD1.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(OD2.Point);
                    result.Add(lines);


                    #endregion
                    break;

                case AminoType.TRP:
                    #region
                    CB = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CB);
                    CG = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CG);
                    CD1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD1);
                    CD2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CD2);
                    CE2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE2);
                    NE1 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.NE1);
                    CZ2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CZ2);
                    CE3 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CE3);
                    var CZ3 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CZ3);
                    var CH2 = amino.Atoms.FirstOrDefault(s => s.AtomType == AtomType.CH2);
                    if (CB == null || CG == null || CD1 == null || CD2 == null
                        || CE2 == null || NE1 == null || CZ2 == null || CE3 == null 
                        || CZ3 == null || CH2 == null)
                        return result;
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CA.Point);
                    lines.Points.Add(CB.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CB.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CG.Point);
                    lines.Points.Add(CD1.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD1.Point);
                    lines.Points.Add(NE1.Point);
                    result.Add(lines);

                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(NE1.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CG.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CD2.Point);
                    lines.Points.Add(CE3.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CE3.Point);
                    lines.Points.Add(CZ3.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ3.Point);
                    lines.Points.Add(CH2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CH2.Point);
                    lines.Points.Add(CZ2.Point);
                    result.Add(lines);
                    lines = new LinesVisual3D { Color = Colors.White };
                    lines.Points.Add(CZ2.Point);
                    lines.Points.Add(CE2.Point);
                    result.Add(lines);


                    #endregion
                    break;

                default:
                    break;
            }
            return result;
        }

        private void ElementOnMouseDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            var element = sender as ModelUIElement3D;
            Amino amino = (from a in Models.Where(s => CurrentModelNumber.Contains(s.Key)).Select(s => s.Value)
                           from amin in a
                           where amin.Atoms.Any(s => s.ModelUiElement3D == element)
                           select amin).FirstOrDefault();
            foreach (var atom in amino.Atoms)
            {
                var model = (GeometryModel3D)atom.ModelUiElement3D.Model;
                if (model.Material == SelectedMaterial)
                {
                    var me = new MeshBuilder();
                    me.AddSphere(atom.Point, 0.08);
                    model.Geometry = me.ToMesh();
                    model.Material = Utils.GetColorByAtomType(atom.AtomType);
                    SelectedModelUIs.Remove(element);
                }
                else
                {
                    var me = new MeshBuilder();
                    me.AddSphere(atom.Point, 0.15);
                    model.Geometry = me.ToMesh();
                    model.Material = SelectedMaterial;
                    SelectedModelUIs.Add(element);
                }
            }
            //Atom atom  = (from a in Models.Where(s => CurrentModelNumber.Contains(s.Key)).Select(s => s.Value)
            //            from amino in a
            //            from atomy in amino.Atoms
            //            where atomy.ModelUiElement3D == element
            //            select atomy).FirstOrDefault();






        }

        private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
        {
            var ch = sender as CheckBox;
            int index = Convert.ToInt32(ch.Content);
            if (ch.IsChecked.HasValue && ch.IsChecked.Value && !CurrentModelNumber.Contains(index))
            {
                CurrentModelNumber.Add(index);
                UIChildren.Add(index, new List<object>());
                foreach (var amino in Models[index])
                {
                    foreach (Visual3D t in DrawAmino(amino))
                    {
                        view1.Children.Add(t);
                        UIChildren[index].Add(t);
                    }
                }
                foreach (var connect in DrawConnections(Models[index]))
                {
                    view1.Children.Add(connect);
                    UIChildren[index].Add(connect);
                }
            }
            view1.ZoomExtents(500);

        }

        private void CheckBox_Unchecked_1(object sender, RoutedEventArgs e)
        {
            var ch = sender as CheckBox;
            int index = Convert.ToInt32(ch.Content);
            if (ch.IsChecked.HasValue && !ch.IsChecked.Value &&
                    CurrentModelNumber.Contains(index))
            {
                CurrentModelNumber.Remove(index);
                foreach (Visual3D val in UIChildren[index])
                {
                    view1.Children.Remove(val);
                    //SelectedModelUIs.Remove(val);
                }
                UIChildren.Remove(index);
            }
        }

        private void ClearMenuItem_OnClick(object sender, RoutedEventArgs e)
        {
            foreach (var modelUiElement3D in SelectedModelUIs)
            {
                var model = (GeometryModel3D) modelUiElement3D.Model;

                var me = new MeshBuilder();
                Atom atom = (from a in Models.Where(s => CurrentModelNumber.Contains(s.Key)).Select(s => s.Value)
                             from amino in a
                             from atomy in amino.Atoms
                             where atomy.ModelUiElement3D == modelUiElement3D
                             select atomy).FirstOrDefault();

                me.AddSphere(atom.Point, 0.08);
                model.Geometry = me.ToMesh();
                model.Material = Utils.GetColorByAtomType(atom.AtomType);
            }
            SelectedModelUIs.Clear();
            DihedralAnglesTextBox.Text = default(string);

        }

    }
}
